﻿using TianYu.Core.Common;
using System.Collections.Concurrent;

namespace SqlSugar
{
    public static partial class ISqlSugarClientExtension
    {
        private readonly static ConcurrentDictionary<string, EntityColumnInfo> _entityKeyColumnInfo = new ConcurrentDictionary<string, EntityColumnInfo>();
        public static async Task CheckFieldValueAsync<TEntity>(this ISqlSugarClient @this, string fieldName, long FieldValue, params long[] ids)
              where TEntity : class, new()
        {
            var entityDbTableInfo = GetEntityDbTableInfo<TEntity>(@this, fieldName);
            //SELECT Count(1) FROM TableName WHERE TID=1 AND ID=1
            var sql = $"SELECT Count(1) FROM {entityDbTableInfo.tableName} WHERE {fieldName} = {FieldValue} AND ";
            if (ids.Length == 1)
            {
                sql += $"{entityDbTableInfo.primaryKey} = {ids[0]} ;";
            }
            else
            {
                sql += $"{entityDbTableInfo.primaryKey} IN( {string.Join(",", ids)} );";
            }
            if ((await @this.Ado.GetIntAsync(sql)) != ids.Length)
            {
                throw new IllegalOperationException();
            }
        }

        public static async Task<TEntity> GetWithCheckFieldValueAsync<TEntity>(this ISqlSugarClient @this, string fieldName, long FieldValue, long id)
            where TEntity : class, new()
        {
            var entityDbTableInfo = GetEntityDbTableInfo<TEntity>(@this, fieldName);
            //SELECT * FROM TableName WHERE TID=1 AND ID=1
            var sql = $"SELECT * FROM {entityDbTableInfo.tableName} WHERE {fieldName} = {FieldValue} AND {entityDbTableInfo.primaryKey} = {id} ;";
            var entity = await @this.SqlQueryable<TEntity>(sql).SingleAsync();
            if (entity == null)
            {
                throw new IllegalOperationException();
            }
            return entity;
        }

        private static (string tableName, string primaryKey) GetEntityDbTableInfo<TEntity>(ISqlSugarClient sqlSugarClient, string checkColumnName)
            where TEntity : class, new()
        {
            var entityInfo = sqlSugarClient.EntityMaintenance.GetEntityInfo<TEntity>();
            if (string.IsNullOrWhiteSpace(entityInfo.DbTableName))
            {
                throw new ArgumentNullException($"{entityInfo.Type.FullName}未设置[SugarTable]");
            }
            var keyProperty = sqlSugarClient.GetEntityPrimaryKeyProperty<TEntity>();
            if (entityInfo.Columns.Where(a => string.Equals(checkColumnName, a.DbColumnName, StringComparison.OrdinalIgnoreCase)).Count() < 1)
            {
                throw new ArgumentNullException($"{entityInfo.Type.FullName}不包含[{checkColumnName}]属性");
            }
            return (entityInfo.DbTableName, keyProperty.DbColumnName);
        }

        public static EntityColumnInfo GetEntityPrimaryKeyProperty<TEntity>(this ISqlSugarClient @this)
          where TEntity : class, new()
        {
            var key = typeof(TEntity).FullName;
            return _entityKeyColumnInfo.GetOrAdd(key, key =>
            {
                var entityInfo = @this.EntityMaintenance.GetEntityInfo<TEntity>();
                var primaryKeys = entityInfo.Columns.Where(a => a.IsPrimarykey);
                if (primaryKeys.Count() < 1)
                {
                    throw new ArgumentNullException($"{entityInfo.Type.FullName}缺少IsPrimaryKey=true的属性");
                }
                if (primaryKeys.Count() > 1)
                {
                    throw new ArgumentNullException($"{entityInfo.Type.FullName}包含多个IsPrimaryKey=true的属性");
                }
                return primaryKeys.First();
            });
        }

        public static (string propertyName, object propertyValue) GetEntityPrimaryKey<TEntity>(this ISqlSugarClient @this, TEntity entity)
            where TEntity : class, new()
        {
            var entityDbTableInfo = GetEntityPrimaryKeyProperty<TEntity>(@this);
            return (entityDbTableInfo.PropertyInfo.Name, entityDbTableInfo.PropertyInfo.GetValue(entity));
        }
    }
}
